/*
 * ksamp_options.c
 *
 * Estructura de datos representando opciones de línea de comandos; con
 * operaciones para parseo y validación a partir de argc, argv.
 *
 */

#include <stdlib.h>
#include <assert.h>

#include "ksamp_options.h"

/* implementación del tipo Options */
struct _options_t {
	ksamp_mode mode;
	int interval, duration; /* Definidos sólo cuando mode==MODE_LOOPED */
	bstring error;          /* Definido sólo cuando hubo error */
};

/*** Inicialización y destrucción ***/

Options *parse_options (int argc, char **argv) {
	Options *result = NULL;
	
	assert (argc > 0);
	assert (argv != NULL);
	
	result = calloc (1, sizeof (*result));
	assert (result != NULL);
	
	result->error = NULL;

	if (argc == 1) {
		/* Invocación: "ksamp" */
		result->mode = MODE_SIMPLE;
	} else if (argc == 2 && strcmp (argv[1], "-s") == 0) {
		/* Invocación: "ksamp -s" */
		result->mode = MODE_STATISTICS;
	} else if (argc == 4 && strcmp (argv[1], "-l") == 0) {
		/* Invocación: "ksamp -l <i> <d>" */
		char *endptr = NULL; /* Ver man strtol */

		result->mode = MODE_LOOPED;
		result->interval = strtol (argv[2], &endptr, 10);
		if (*argv[2] == '\0' || *endptr != '\0' || result->interval <= 0) {
			result->error = bformat (
				"Intervalo de ciclo no válido: '%s'\n", argv[2]);
		}
		result->duration = strtol (argv[3], &endptr, 10);
		if (*argv[3] == '\0' || *endptr != '\0' || result->duration < 0) {
			result->error = bformat (
				"Duración de ciclo no válida: '%s'\n", argv[3]);
		}
	} else if (argc == 2 && strcmp (argv[1], "--help") == 0) {
		result->error = bfromcstr ("");
	} else {
		result->error = bfromcstr ("Argumentos no válidos.\n");
	}

	return result;
}

/*** Consultas ***/

void options_destroy (Options *self) {
	assert (self != NULL);

	bdestroy (self->error);
	free (self);
}

bool options_is_valid (Options *self) {
	assert (self != NULL);

	return (self->error == NULL);
}

ksamp_mode options_get_mode (Options *self) {
	assert (self != NULL);
	assert (options_is_valid (self));

	return self->mode;
}

int options_get_interval (Options *self) {
	assert (self != NULL);
	assert (options_is_valid (self));
	assert (options_get_mode (self) == MODE_LOOPED);

	return self->interval;
}

int options_get_duration (Options *self) {
	assert (self != NULL);
	assert (options_is_valid (self));
	assert (options_get_mode (self) == MODE_LOOPED);

	return self->duration;
}

const_bstring options_get_error (Options *self) {
	assert (self != NULL);
	assert (!options_is_valid (self));
	
	return self->error;
}
